#!/usr/bin/env python3
"""
文本计数统计程序 - 最终修复版本
修复句子统计逻辑
"""

import re
import sys
import argparse
import unittest
import tempfile
import os
import time
import random
import string
from pathlib import Path
from typing import Dict, Tuple


class TextCounter:
    """文本计数器类"""
    
    def __init__(self, file_path: str):
        self.file_path = Path(file_path)
        if not self.file_path.exists():
            raise FileNotFoundError(f"文件不存在: {file_path}")
        
        try:
            self.content = self.file_path.read_text(encoding='utf-8')
        except UnicodeDecodeError:
            # 如果UTF-8失败，尝试其他编码
            try:
                self.content = self.file_path.read_text(encoding='gbk')
            except:
                self.content = self.file_path.read_text(encoding='latin-1')
    
    def count_chars(self) -> int:
        """统计字符数（包括空格和换行符）"""
        return len(self.content)
    
    def count_words(self) -> int:
        """统计单词数（基于空格分隔）"""
        # 匹配字母数字字符序列，包括连字符和撇号
        words = re.findall(r'\b[a-zA-Z0-9\'-]+\b', self.content)
        return len(words)
    
    def count_sentences(self) -> int:
        """统计句子数（基于句号、问号、感叹号分隔）"""
        # 简化但可靠的句子统计方法
        # 1. 先将文本按行分割
        lines = self.content.split('\n')
        sentence_count = 0
        
        for line in lines:
            line = line.strip()
            if not line:
                continue
                
            # 2. 在每行中查找句子结束符
            # 使用简单的正则表达式匹配句子结束
            sentences_in_line = re.split(r'[.!?]+', line)
            # 过滤空字符串
            sentences_in_line = [s.strip() for s in sentences_in_line if s.strip()]
            sentence_count += len(sentences_in_line)
        
        return sentence_count
    
    def count_lines(self) -> int:
        """统计总行数"""
        return len(self.content.splitlines())
    
    def count_code_stats(self) -> Tuple[int, int, int]:
        """
        统计代码行、空行、注释行
        适用于Python文件
        """
        if not self.file_path.suffix == '.py':
            return 0, 0, 0
        
        lines = self.content.split('\n')
        code_lines = 0
        empty_lines = 0
        comment_lines = 0
        
        in_multiline_comment = False
        
        for line in lines:
            stripped_line = line.strip()
            
            # 检查空行
            if not stripped_line:
                empty_lines += 1
                continue
            
            # 检查多行注释
            if in_multiline_comment:
                comment_lines += 1
                if '"""' in stripped_line or "'''" in stripped_line:
                    in_multiline_comment = False
                continue
            
            # 检查多行注释开始
            if stripped_line.startswith('"""') or stripped_line.startswith("'''"):
                comment_lines += 1
                in_multiline_comment = True
                # 检查是否在同一行结束
                if stripped_line.count('"""') >= 2 or stripped_line.count("'''") >= 2:
                    in_multiline_comment = False
                continue
            
            # 检查单行注释
            if stripped_line.startswith('#'):
                comment_lines += 1
            else:
                code_lines += 1
        
        return code_lines, empty_lines, comment_lines
    
    def get_all_stats(self) -> Dict[str, int]:
        """获取所有统计信息"""
        code_lines, empty_lines, comment_lines = self.count_code_stats()
        
        return {
            'chars': self.count_chars(),
            'words': self.count_words(),
            'sentences': self.count_sentences(),
            'lines': self.count_lines(),
            'code_lines': code_lines,
            'empty_lines': empty_lines,
            'comment_lines': comment_lines
        }


def create_test_file():
    """创建测试文件"""
    test_content = """Hello world! This is a test file.
This is the second sentence. And the third one!

Let's count some words and characters.
This should be enough for testing."""
    
    with open('test.txt', 'w', encoding='utf-8') as f:
        f.write(test_content)
    print("创建测试文件: test.txt")


def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description='文本计数统计程序 - 统计文本文件的字符数、单词数、句子数等',
        prog='wc'
    )
    
    # 将文件参数改为可选的，并提供默认测试
    parser.add_argument(
        'file',
        nargs='?',  # 使文件参数变为可选
        help='要统计的文本文件路径（如未提供，使用测试文件）'
    )
    
    parser.add_argument(
        '-c', '--chars',
        action='store_true',
        help='统计字符数'
    )
    
    parser.add_argument(
        '-w', '--words',
        action='store_true',
        help='统计单词数'
    )
    
    parser.add_argument(
        '-s', '--sentences',
        action='store_true',
        help='统计句子数'
    )
    
    parser.add_argument(
        '-l', '--lines',
        action='store_true',
        help='统计行数'
    )
    
    parser.add_argument(
        '-a', '--all',
        action='store_true',
        help='显示所有统计信息'
    )
    
    parser.add_argument(
        '--code',
        action='store_true',
        help='统计代码行数（仅对Python文件有效）'
    )
    
    parser.add_argument(
        '--empty',
        action='store_true',
        help='统计空行数'
    )
    
    parser.add_argument(
        '--comment',
        action='store_true',
        help='统计注释行数'
    )
    
    parser.add_argument(
        '--create-test',
        action='store_true',
        help='创建测试文件'
    )
    
    args = parser.parse_args()
    
    # 如果请求创建测试文件
    if args.create_test:
        create_test_file()
        print("测试文件已创建，可以使用: wc test.txt 或 wc -a test.txt")
        return
    
    # 如果没有提供文件且没有其他操作，显示帮助
    if args.file is None and not args.create_test:
        parser.print_help()
        print("\n示例:")
        print("  wc test.txt              # 基础统计")
        print("  wc -c test.txt           # 只统计字符数")
        print("  wc -a test.txt           # 显示所有统计")
        print("  wc --create-test         # 创建测试文件")
        return
    
    # 使用测试文件如果未指定文件
    target_file = args.file if args.file else 'test.txt'
    
    try:
        counter = TextCounter(target_file)
        
        # 显示所有统计信息
        if args.all:
            stats = counter.get_all_stats()
            print(f"文件: {target_file}")
            print(f"字符数: {stats['chars']}")
            print(f"单词数: {stats['words']}")
            print(f"句子数: {stats['sentences']}")
            print(f"总行数: {stats['lines']}")
            if counter.file_path.suffix == '.py':
                print(f"代码行: {stats['code_lines']}")
                print(f"空行数: {stats['empty_lines']}")
                print(f"注释行: {stats['comment_lines']}")
            return
        
        # 单个统计项
        results = []
        
        if args.chars:
            results.append(f"字符数: {counter.count_chars()}")
        
        if args.words:
            results.append(f"单词数: {counter.count_words()}")
        
        if args.sentences:
            results.append(f"句子数: {counter.count_sentences()}")
        
        if args.lines:
            results.append(f"行数: {counter.count_lines()}")
        
        if args.code:
            code_lines, _, _ = counter.count_code_stats()
            results.append(f"代码行: {code_lines}")
        
        if args.empty:
            _, empty_lines, _ = counter.count_code_stats()
            results.append(f"空行数: {empty_lines}")
        
        if args.comment:
            _, _, comment_lines = counter.count_code_stats()
            results.append(f"注释行: {comment_lines}")
        
        # 输出结果
        if results:
            for result in results:
                print(result)
        else:
            # 如果没有指定任何参数，显示基础统计
            stats = counter.get_all_stats()
            print(f"文件: {target_file}")
            print(f"字符数: {stats['chars']}")
            print(f"单词数: {stats['words']}")
            print(f"句子数: {stats['sentences']}")
            print(f"总行数: {stats['lines']}")
    
    except FileNotFoundError as e:
        print(f"错误: {e}")
        print("使用 --create-test 参数创建测试文件")
        sys.exit(1)
    except Exception as e:
        print(f"处理文件时发生错误: {e}")
        sys.exit(1)


# ============================================================================
# 最终修复的单元测试部分
# ============================================================================

class TestTextCounter(unittest.TestCase):
    """文本计数器测试类"""
    
    def setUp(self):
        """测试前准备"""
        # 明确的3个句子测试内容
        self.test_content = "Hello world! This is a test. This is the second sentence."
        self.test_file = tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8')
        self.test_file.write(self.test_content)
        self.test_file.close()
    
    def tearDown(self):
        """测试后清理"""
        if os.path.exists(self.test_file.name):
            os.unlink(self.test_file.name)
    
    def test_count_chars(self):
        """测试字符数统计"""
        counter = TextCounter(self.test_file.name)
        self.assertEqual(counter.count_chars(), len(self.test_content))
    
    def test_count_words(self):
        """测试单词数统计"""
        counter = TextCounter(self.test_file.name)
        # "Hello world! This is a test. This is the second sentence."
        # 单词: Hello, world, This, is, a, test, This, is, the, second, sentence
        self.assertEqual(counter.count_words(), 11)
    
    def test_count_sentences(self):
        """测试句子数统计"""
        counter = TextCounter(self.test_file.name)
        # 3个句子：以! . . 结尾
        self.assertEqual(counter.count_sentences(), 3)
    
    def test_file_not_found(self):
        """测试文件不存在的情况"""
        with self.assertRaises(FileNotFoundError):
            TextCounter("nonexistent_file.txt")
    
    def test_empty_file(self):
        """测试空文件"""
        empty_file = tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8')
        empty_file.close()
        
        counter = TextCounter(empty_file.name)
        self.assertEqual(counter.count_chars(), 0)
        self.assertEqual(counter.count_words(), 0)
        self.assertEqual(counter.count_sentences(), 0)
        
        if os.path.exists(empty_file.name):
            os.unlink(empty_file.name)


class TestEdgeCases(unittest.TestCase):
    """边界情况测试"""
    
    def test_only_punctuation(self):
        """测试只有标点符号的情况"""
        # 只有标点符号不应该被计为句子
        content = "!!! ... ???"
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8') as f:
            f.write(content)
            f.close()
            
            counter = TextCounter(f.name)
            self.assertEqual(counter.count_words(), 0)
            # 只有标点符号不应该被计为句子
            self.assertEqual(counter.count_sentences(), 0)
            
            if os.path.exists(f.name):
                os.unlink(f.name)
    
    def test_multiple_spaces(self):
        """测试多个空格的情况"""
        content = "apple    banana   cherry"
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8') as f:
            f.write(content)
            f.close()
            
            counter = TextCounter(f.name)
            self.assertEqual(counter.count_words(), 3)
            
            if os.path.exists(f.name):
                os.unlink(f.name)
    
    def test_contractions(self):
        """测试包含撇号的单词"""
        content = "I'm don't it's we're"
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8') as f:
            f.write(content)
            f.close()
            
            counter = TextCounter(f.name)
            # I'm, don't, it's, we're - 4个单词
            self.assertEqual(counter.count_words(), 4)
            
            if os.path.exists(f.name):
                os.unlink(f.name)
    
    def test_hyphenated_words(self):
        """测试包含连字符的单词"""
        content = "mother-in-law twenty-three state-of-the-art"
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8') as f:
            f.write(content)
            f.close()
            
            counter = TextCounter(f.name)
            # mother-in-law, twenty-three, state-of-the-art - 3个单词
            self.assertEqual(counter.count_words(), 3)
            
            if os.path.exists(f.name):
                os.unlink(f.name)
    
    def test_simple_sentences(self):
        """测试简单句子"""
        content = "This is sentence one. This is sentence two! Is this sentence three?"
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8') as f:
            f.write(content)
            f.close()
            
            counter = TextCounter(f.name)
            # 3个句子
            self.assertEqual(counter.count_sentences(), 3)
            
            if os.path.exists(f.name):
                os.unlink(f.name)


# ============================================================================
# 演示和测试函数
# ============================================================================

def test_basic_functionality():
    """测试基础功能"""
    print("=== 基础功能测试 ===\n")
    
    # 创建测试文件
    test_content = """Hello world! This is a test file.
This is the second sentence. And the third one!

Let's count some words and characters.
This should be enough for testing."""
    
    with open('test.txt', 'w', encoding='utf-8') as f:
        f.write(test_content)
    print("创建测试文件: test.txt")
    
    # 测试统计功能
    counter = TextCounter('test.txt')
    
    print("统计结果:")
    print(f"字符数: {counter.count_chars()}")
    print(f"单词数: {counter.count_words()}")
    print(f"句子数: {counter.count_sentences()}")
    print(f"行数: {counter.count_lines()}")
    
    print("\n完整统计:")
    stats = counter.get_all_stats()
    for key, value in stats.items():
        print(f"{key}: {value}")
    
    # 清理
    if os.path.exists('test.txt'):
        os.remove('test.txt')

def test_python_file():
    """测试Python文件分析"""
    print("\n=== Python文件分析测试 ===\n")
    
    # 创建Python测试文件
    python_code = '''#!/usr/bin/env python3
"""
这是一个测试Python文件
用于演示代码统计功能
"""

def hello_world():
    """打印hello world"""
    print("Hello, World!")  # 这是一个注释
    
    
def main():
    # 主函数
    hello_world()


if __name__ == "__main__":
    main()
'''
    
    with open('test.py', 'w', encoding='utf-8') as f:
        f.write(python_code)
    
    counter = TextCounter('test.py')
    stats = counter.get_all_stats()
    
    print("Python文件统计:")
    for key, value in stats.items():
        print(f"{key}: {value}")
    
    # 清理
    if os.path.exists('test.py'):
        os.remove('test.py')

def run_unit_tests():
    """运行单元测试"""
    print("\n=== 单元测试 ===")
    
    # 创建测试套件
    loader = unittest.TestLoader()
    suite = unittest.TestSuite()
    
    # 添加测试类
    suite.addTests(loader.loadTestsFromTestCase(TestTextCounter))
    suite.addTests(loader.loadTestsFromTestCase(TestEdgeCases))
    
    # 运行测试
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)
    
    return result.wasSuccessful()

def performance_test():
    """性能测试"""
    print("\n=== 性能测试 ===\n")
    
    # 生成测试内容 - 使用真实的单词和句子
    words = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig', 'grape']
    sentences = []
    
    for _ in range(100):  # 生成100个句子
        sentence = ' '.join(random.choices(words, k=random.randint(5, 15)))
        sentence = sentence.capitalize() + random.choice(['.', '!', '?'])
        sentences.append(sentence)
    
    content = ' '.join(sentences)
    
    with open('performance_test.txt', 'w', encoding='utf-8') as f:
        f.write(content)
    
    print(f"生成测试文件: performance_test.txt ({len(content)} 字符)")
    
    counter = TextCounter('performance_test.txt')
    
    # 测试字符统计性能
    start_time = time.time()
    chars_count = counter.count_chars()
    chars_time = time.time() - start_time
    
    # 测试单词统计性能
    start_time = time.time()
    words_count = counter.count_words()
    words_time = time.time() - start_time
    
    # 测试句子统计性能
    start_time = time.time()
    sentences_count = counter.count_sentences()
    sentences_time = time.time() - start_time
    
    print(f"\n性能结果:")
    print(f"字符统计: {chars_time:.4f}秒 (结果: {chars_count})")
    print(f"单词统计: {words_time:.4f}秒 (结果: {words_count})")
    print(f"句子统计: {sentences_time:.4f}秒 (结果: {sentences_count})")
    
    # 清理
    if os.path.exists('performance_test.txt'):
        os.remove('performance_test.txt')

def comprehensive_demo():
    """综合演示"""
    print("文本计数统计程序 - 完整功能演示")
    print("=" * 60)
    
    # 运行所有测试
    test_basic_functionality()
    print("\n" + "-" * 60)
    
    test_python_file()
    print("\n" + "-" * 60)
    
    performance_test()
    print("\n" + "-" * 60)
    
    # 运行单元测试
    success = run_unit_tests()
    
    if success:
        print("\n🎉 恭喜！所有功能测试通过！")
        print("✅ 基础功能正常")
        print("✅ 扩展功能正常") 
        print("✅ 单元测试通过")
        print("✅ 性能测试完成")
        print("\n可以开始版本提交到码云了！")
    else:
        print("\n❌ 部分测试失败，请检查代码。")


# ============================================================================
# 主程序入口
# ============================================================================

if __name__ == '__main__':
    # 如果没有命令行参数，运行演示
    if len(sys.argv) == 1:
        comprehensive_demo()
    else:
        # 否则运行命令行程序
        main()
